package cn.xzqwjw.taskmanager.utils;

import cn.xzqwjw.taskmanager.common.exception.CustomException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.extern.slf4j.Slf4j;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * jackson 的json相关操作工具类
 *
 * @author rush
 */
@Slf4j
public class JsonUtil {

  public static ObjectMapper objectMapper = new ObjectMapper();

  /**
   * 对象转 Json 字符串
   *
   * @param obj 被转化的对象
   * @return Json 字符串
   */
  public static String obj2Json(Object obj) {
    String result;
    try {
      result = objectMapper.writeValueAsString(obj);
      // 美化输出，输出的json包括 \r\n \" 啥的，没什么用处
      // result = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
    } catch (JsonProcessingException e) {
      log.error("obj2Json() 出现 JsonProcessingException 异常：{}", e.getMessage());
      throw new CustomException(e.getMessage());
    }
    return result;
  }

  /**
   * 对象转 byte 数组
   *
   * @param obj Java对象
   * @return byte数组
   */
  public static byte[] obj2Bytes(Object obj) {
    try {
      return objectMapper.writeValueAsBytes(obj);
    } catch (JsonProcessingException e) {
      log.error("obj2Bytes() 出现 JsonProcessingException 异常：{}", e.getMessage());
      throw new CustomException(e.getMessage());
    }
  }

  /**
   * Json 字符串转对象
   *
   * @param jsonString 被转化的json字符串
   * @param clazz      转化的对象 class 类型
   * @param <T>        泛型
   * @return 转化的对象
   */
  public static <T> T json2Obj(String jsonString, Class<T> clazz) {
    try {
      return objectMapper.readValue(jsonString, clazz);
    } catch (JsonProcessingException e) {
      log.error("json2Obj() 出现 JsonProcessingException 异常：{}", e.getMessage());
      throw new CustomException(e.getMessage());
    }
  }

  /**
   * Json 字符串转对象
   *
   * @param jsonString 被转化的json字符串
   * @return 转化的对象
   */
  public static Map<?, ?> json2Map(String jsonString) {
    try {
      return objectMapper.readValue(jsonString, Map.class);
    } catch (JsonProcessingException e) {
      log.error("json2Map() 出现 JsonProcessingException 异常：{}", e.getMessage());
      throw new CustomException(e.getMessage());
    }
  }

  /**
   * Json 字符串转 List
   *
   * @param jsonString     被转化的json字符串
   * @param elementClasses 转化的对象 class 类型
   * @param <T>            泛型
   * @return 转化的List
   */
  @SafeVarargs
  public static <T> List<T> json2List(String jsonString, Class<T>... elementClasses) {
    try {
      return objectMapper.readValue(jsonString, getCollectionType(objectMapper, List.class, elementClasses));
    } catch (Exception e) {
      log.error("json2List() 出现异常，jsonString：{}， elementClassesName：{} \n",
          jsonString, elementClasses.getClass().getName(), e);
      throw new CustomException(e.getMessage());
    }
  }

  /**
   * Json 字符串转 Set
   *
   * @param jsonString     被转化的json字符串
   * @param elementClasses 转化的对象 class 类型
   * @param <T>            泛型
   * @return 转化的 Set
   */
  @SafeVarargs
  public static <T> Set<T> json2Set(String jsonString, Class<T>... elementClasses) {
    try {
      return objectMapper.readValue(jsonString,
          getCollectionType(objectMapper, Set.class, elementClasses));
    } catch (Exception e) {
      log.error("json2Set() 出现异常，jsonString：{}， elementClassesName：{} \n",
          jsonString, elementClasses.getClass().getName(), e);
      throw new CustomException(e.getMessage());
    }
  }

  /**
   * Json 字符串转 Collection
   *
   * @param jsonString     被转化的json字符串
   * @param elementClasses 转化的对象 class 类型
   * @param <T>            泛型
   * @return 转化的 Collection
   */
  @SafeVarargs
  public static <T> Collection<T> json2Collection(String jsonString, Class<T>... elementClasses) {
    try {
      return objectMapper.readValue(jsonString,
          getCollectionType(objectMapper, Collection.class, elementClasses));
    } catch (Exception e) {
      log.error("json2Collection() 出现异常，jsonString：{}， elementClassesName：{} \n",
          jsonString, elementClasses.getClass().getName(), e);
      throw new CustomException(e.getMessage());
    }
  }

  /**
   * 获取泛型的Collection Type
   *
   * @param collectionClass 泛型的Collection
   * @param elementClasses  元素类
   * @return JavaType Java类型
   * @since 1.0
   */
  public static JavaType getCollectionType(ObjectMapper mapper,
                                           Class<?> collectionClass,
                                           Class<?>... elementClasses) {
    return mapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);
  }

  /**
   * 将两个对象合并成一个对象并返回json
   *
   * @param o1 一个对象
   * @param o2 另一个对象
   * @return 合并后的对象的json
   */
  public static String mergeObj(Object o1, Object o2) {
    ObjectNode root, node;
    try {
      root = objectMapper.valueToTree(o1);
    } catch (IllegalArgumentException e) {
      log.error("mergeObj() 报 IllegalArgumentException 异常：{}", e.getMessage());
      throw new CustomException(e.getMessage());
    }
    try {
      node = objectMapper.valueToTree(o2);
    } catch (IllegalArgumentException e) {
      log.error("mergeObj() 报 IllegalArgumentException 异常：{}", e.getMessage());
      throw new CustomException(e.getMessage());
    }
    root.setAll(node);
    String returnString;
    try {
      returnString = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(root);
    } catch (JsonProcessingException e) {
      log.error("mergeObj() 报 JsonProcessingException 异常：{}", e.getMessage());
      throw new CustomException(e.getMessage());
    }
    return returnString;
  }

}
